"""
@author: 江同学呀
@file: shape_queries.py
@date: 2025/1/13 20:36
@desc:
    形状查询
    https://www.elastic.co/guide/en/elasticsearch/reference/7.17/shape-queries.html

    Like geo_shape Elasticsearch supports the ability to index arbitrary two dimension (non Geospatial) geometries
    making it possible to map out virtual worlds, sporting venues, theme parks, and CAD diagrams.
    与 geo_shape 一样，Elasticsearch 支持为任意二维（非地理空间）几何图形编制索引，从而可以绘制出虚拟世界、体育场馆、主题公园和 CAD 图表。

    Elasticsearch supports two types of cartesian data: point fields which support x/y pairs, and shape fields, which
    support points, lines, circles, polygons, multi-polygons, etc.
    Elasticsearch 支持两种类型的笛卡尔数据：支持 x/y 对的点字段，以及支持点、线、圆、多边形、多多边形等的形状字段。
"""
from typing import Union, Literal, Dict

from espc.common.query_common import SpatialRelation
from espc.orm.model.struct.geo import Shape as Shp
from espc.orm.model.dsl.queries.base_queries import _BaseQueries
from espc.orm.model.mapping.field.base_field.base_field import _BaseField


class Shape(_BaseQueries):
    """
    形状查询
    https://www.elastic.co/guide/en/elasticsearch/reference/7.17/shape-queries.html

    Queries documents that contain fields indexed using the shape type.
    Requires the shape Mapping.
    The query supports two ways of defining the target shape, either by providing a whole shape definition, or by
    referencing the name, or id, of a shape pre-indexed in another index. Both formats are defined below with examples.

    查询包含使用 shape 类型编制索引的字段的文档。
    需要 shape Mapping。
    该查询支持两种定义目标形状的方法，要么提供完整的形状定义，要么引用在另一个索引中预先编制索引的形状的名称或 id。下面通过示例定义了这两种格式。

    :param field:
    :param ignore_unmapped:
    :param shape:
    :param indexed_shape:
    :param relation:
    """
    type: str = "shape"

    def __init__(
            self, field: Union[str, _BaseField], ignore_unmapped: bool = None,
            shape: Union[Dict, Shp] = None, indexed_shape: Dict[Literal["id", "index", "path", "routing"], str] = None,
            relation: Union[Literal["INTERSECTS", "DISJOINT", "CONTAINS", "WITHIN"], SpatialRelation] = None
    ):
        super().__init__()
        self._field: Union[str, _BaseField] = field
        self._ignore_unmapped: bool = ignore_unmapped
        self._shape: Union[Dict, Shp] = shape
        self._indexed_shape: Dict[Literal["id", "index", "path", "routing"], str] = indexed_shape
        self._relation: Union[Literal["INTERSECTS", "DISJOINT", "CONTAINS", "WITHIN"], SpatialRelation, None] = relation
        return

    def _build(self) -> Dict:
        _body: Dict = {}
        if self._shape is not None:
            _body["shape"] = self._shape if isinstance(self._shape, Dict) else self._shape._build()
        if self._indexed_shape is not None:
            _body["indexed_shape"] = self._indexed_shape
        if self._relation is not None:
            _body["relation"] = self._relation.value
        return {
            self._field if isinstance(self._field, str) else self._field._field_name: _body
        }





















